﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using System.Linq.Expressions;
using System.Text;
using IceTea.Security;
using IceTea.Domain;

namespace IceTea.Infrastructure
{
    public static class CustomHelpers
    {
        public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper,
           string linkText,
           string actionName,
           string controllerName,
           SecurityRole securityRole)
        {
            MvcHtmlString link = MvcHtmlString.Empty;
            if (htmlHelper.IsVisible(securityRole))
            {
                link = htmlHelper.ActionLink(linkText, actionName, controllerName);
            }

            return link;
        }
        
        public static bool IsVisible(this HtmlHelper htmlHelper, SecurityRole securityRole)
        {
            return new IceTeaAuthorizeAttribute(securityRole).PerformAuthorizeCore(htmlHelper.ViewContext.HttpContext);
        }

        #region ComboBox
        public static MvcHtmlString ComboBoxFor<TModel, TProperty>(
            this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<string> selectList, IDictionary<string, object> htmlAttributes)
        {
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression<TModel, TProperty>(expression, htmlHelper.ViewData);
            string name = ExpressionHelper.GetExpressionText(expression);
            return htmlHelper.internalComboBox(metadata, name, metadata.Model, selectList, htmlAttributes);
        }

        public static MvcHtmlString ComboBoxFor<TModel, TProperty>(
            this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<string> selectList, object htmlAttributes)
        {
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression<TModel, TProperty>(expression, htmlHelper.ViewData);
            string name = ExpressionHelper.GetExpressionText(expression);
            IDictionary<string, object> dictionary = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
            return htmlHelper.internalComboBox(metadata, name, metadata.Model, selectList, dictionary);
        }

        public static MvcHtmlString ComboBox(
            this HtmlHelper htmlHelper, string name, string value, IEnumerable<string> selectList, IDictionary<string, object> htmlAttributes)
        {
            return htmlHelper.internalComboBox(null, name, value, selectList, htmlAttributes);
        }

        private static MvcHtmlString internalComboBox(
            this HtmlHelper htmlHelper, ModelMetadata metadata, string name, object value,
            IEnumerable<string> selectList, IDictionary<string, object> htmlAttributes)
        {
            string fullHtmlFieldName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);
            if (string.IsNullOrEmpty(fullHtmlFieldName))
            {
                throw new ArgumentException("FullHtmlFieldName should not be null or empty");
            }

            TagBuilder inputtext = new TagBuilder("input");
                  
            //<div class='input-group'>
            TagBuilder inputgroup = new TagBuilder("div")
            {
                InnerHtml = GenerateInternalHtml(() =>
                {
                    StringBuilder inputgroupbuilder = new StringBuilder();

                    //<input type='text' class='form-control'>
                    inputtext.MergeAttribute("class", "form-control");
                    inputtext.MergeAttribute("type", "text");
                    inputtext.MergeAttribute("name", fullHtmlFieldName, true);
                    if (value != null)
                        inputtext.MergeAttribute("value", value.ToString(), true);
                    inputtext.MergeAttributes<string, object>(htmlAttributes);
                    inputtext.GenerateId(fullHtmlFieldName);

                    //<div class='input-group-btn'>
                    TagBuilder inputgroupbtn = new TagBuilder("div")
                    {
                        InnerHtml = GenerateInternalHtml(() =>
                        {
                            StringBuilder inputgroupbtnbuilder = new StringBuilder();

                            //<button type='button' class='btn btn-default dropdown-toggle' data-toggle='dropdown'>
                            TagBuilder dropdownbtn = new TagBuilder("button")
                            {
                                InnerHtml = GenerateInternalHtml(() =>
                                {
                                    //<span class='caret'>
                                    TagBuilder span = new TagBuilder("span");
                                    span.MergeAttribute("class", "caret");
                                    return span.ToString(TagRenderMode.Normal);
                                })
                            };
                            dropdownbtn.MergeAttribute("type", "button");
                            dropdownbtn.MergeAttribute("class", "btn btn-default dropdown-toggle");
                            dropdownbtn.MergeAttribute("data-toggle", "dropdown");
                            inputgroupbtnbuilder.AppendLine(dropdownbtn.ToString(TagRenderMode.Normal));

                            //<ul class='dropdown-menu pull-right'>
                            TagBuilder ultag = new TagBuilder("ul")
                            {
                                InnerHtml = GenerateInternalHtml(() =>
                                {
                                    //<li><a href='#'>xxxx</a></li>
                                    StringBuilder listbuilder = new StringBuilder();
                                    foreach (string item in selectList)
                                    {
                                        TagBuilder litag = new TagBuilder("li")
                                        {
                                            InnerHtml = GenerateInternalHtml(() =>
                                            {
                                                TagBuilder linktag = new TagBuilder("a")
                                                {
                                                    InnerHtml = HttpUtility.HtmlEncode(item)
                                                };
                                                linktag.MergeAttribute("href", "#");
                                                linktag.MergeAttribute("onclick", 
                                                    string.Format("onselect_{0}('{1}')", inputtext.Attributes["id"], item));
                                                return linktag.ToString(TagRenderMode.Normal);
                                            })
                                        };
                                        listbuilder.AppendLine(litag.ToString(TagRenderMode.Normal));
                                    }
                                    return listbuilder.ToString();
                                })
                            };
                            ultag.MergeAttribute("class", "dropdown-menu pull-right");
                            inputgroupbtnbuilder.AppendLine(ultag.ToString(TagRenderMode.Normal));

                            return inputgroupbtnbuilder.ToString();
                        })
                    };
                    inputgroupbtn.MergeAttribute("class", "input-group-btn");
          
                    inputgroupbuilder.AppendLine(inputtext.ToString(TagRenderMode.Normal));
                    inputgroupbuilder.AppendLine(inputgroupbtn.ToString(TagRenderMode.Normal));

                    return inputgroupbuilder.ToString();
                })
            };
            inputgroup.MergeAttribute("class", "input-group");

            //javascript part
            TagBuilder script = new TagBuilder("script")
            {
                InnerHtml = GenerateInternalHtml(() =>
                {
                    StringBuilder scriptbuilder = new StringBuilder();
                    scriptbuilder.AppendFormat(@"function onselect_{0}(seltext) ", inputtext.Attributes["id"]);
                    scriptbuilder.Append(" { ");
                    scriptbuilder.AppendFormat(@" $('#{0}').val(seltext);", inputtext.Attributes["id"]);
                    scriptbuilder.Append(" }");
                    return scriptbuilder.ToString();
                })
            };
            script.MergeAttribute("type", "text/javascript");

            //combine the html tag and js
            StringBuilder result = new StringBuilder();
            result.AppendLine(inputgroup.ToString(TagRenderMode.Normal));
            result.AppendLine(script.ToString(TagRenderMode.Normal));
            return new MvcHtmlString(result.ToString());
        }

        private static string GenerateInternalHtml(Func<string> method)
        {
            return method.Invoke();
        }
        #endregion
    }
}